﻿#include "pincfg.h"
#include "lcd_hal.h"
#include "lcd_ext.h"
#include "common.h"
#include "os_obj.h"

/*****************************************************************************
* @brief   extern
*****************************************************************************/
#define delay_us bsp_delay_us
#define delay_ms(x) osDelay(ms_ticks(x) + 1)

/*****************************************************************************
* @brief   LCD端口定义 
*****************************************************************************/
static volatile u8 LCD_LED;

/*****************************************************************************
* @brief   data direction
*****************************************************************************/
static __inline void hal_dat_dir(u8 i0_o1)
{
	intx_alloc();

	intx_disable();

	if (i0_o1)
	{
		GPIOC->MODER |= 0x54000555UL;
		GPIOA->MODER |= 0x00005000UL;
		GPIOE->MODER |= 0x55400000UL;
	}
	else
	{
		GPIOC->MODER &= ~0xFC000FFFUL;
		GPIOA->MODER &= ~0x0000F000UL;
		GPIOE->MODER &= ~0xFFC00000UL;
	}

	intx_enable();
}

/*****************************************************************************
* @brief   io init
*****************************************************************************/
void lcd_hal_io_init(void)
{
	intx_alloc();

	intx_disable();

	// OUT MODE : PP
	GPIOC->OTYPER &= ~(BITS(0, 5) | BITS(13, 15));
	GPIOA->OTYPER &= ~BITS(6, 7);
	GPIOE->OTYPER &= ~BITS(11, 15);

	// OUT SPD  : high speed
	GPIOC->OSPEEDR |= 0xFC000FFFUL;
	GPIOA->OSPEEDR |= 0x0000F000UL;
	GPIOE->OSPEEDR |= 0xFFC00000UL;

	// IN MODE  : float
	GPIOC->PUPDR &= ~0xFC000FFFUL;
	GPIOA->PUPDR &= ~0x0000F000UL;
	GPIOE->PUPDR &= ~0xFFC00000UL;

	intx_enable();

	hal_dat_dir(1);

	lcd_rst.dir_out_pp();
	lcd_rd.mode(PIN_MODE_OUT_SH_PP);
	lcd_rs.mode(PIN_MODE_OUT_SH_PP);
	lcd_cs.mode(PIN_MODE_OUT_SH_PP);
	lcd_wr.mode(PIN_MODE_OUT_SH_PP);
}

/*****************************************************************************
* @brief   var
*****************************************************************************/


/*****************************************************************************
* @brief  read reg
*****************************************************************************/
u16 lcd_reg_read(u16 LCD_Reg)
{
	u16 t;

	lcd_hal_reg_sel(LCD_Reg); //写入要读的寄存器号

	hal_dat_dir(0);

	lcd_hal_rs_high();

	//读取数据(读寄存器时,并不需要读2次)
	lcd_hal_rd_low();
	delay_us(5); //FOR 8989,延时5us

	t = lcd_hal_io16_in();

	lcd_hal_rd_high();

	hal_dat_dir(1);

	return t;
}

/*****************************************************************************
* @brief  设置光标位置
*****************************************************************************/
//Xpos:横坐标
//Ypos:纵坐标
void lcd_cursor_set(u16 Xpos, u16 Ypos)
{
	lcd_hal_cs_low();

#if USE_HORIZONTAL == 1
	lcd_hal_reg_set(0x02, Ypos >> 8);
	lcd_hal_reg_set(0x03, Ypos);
	lcd_hal_reg_set(0x06, Xpos >> 8);
	lcd_hal_reg_set(0x07, Xpos);
#else
	lcd_hal_reg_set(0x02, Xpos >> 8);
	lcd_hal_reg_set(0x03, Xpos);
	lcd_hal_reg_set(0x06, Ypos >> 8);
	lcd_hal_reg_set(0x07, Ypos);
#endif
	lcd_hal_cs_high();
}

void lcd_window_set(u16 x1, u16 y1, u16 x2, u16 y2)
{
	lcd_hal_cs_low();

#if USE_HORIZONTAL == 1
	lcd_hal_reg_set(0x06, x1 >> 8);
	lcd_hal_reg_set(0x07, x1);	
	lcd_hal_reg_set(0x08, x2 >> 8);
	lcd_hal_reg_set(0x09, x2);	
	
	lcd_hal_reg_set(0x02, y1 >> 8);
	lcd_hal_reg_set(0x03, y1);
	lcd_hal_reg_set(0x04, y2 >> 8);
	lcd_hal_reg_set(0x05, y2);
#else
	lcd_hal_reg_set(0x06, y1 >> 8);
	lcd_hal_reg_set(0x07, y1);	
	lcd_hal_reg_set(0x08, y2 >> 8);
	lcd_hal_reg_set(0x09, y2);	
	
	lcd_hal_reg_set(0x02, x1 >> 8);
	lcd_hal_reg_set(0x03, x1);
	lcd_hal_reg_set(0x04, x2 >> 8);
	lcd_hal_reg_set(0x05, x2);

#endif
	lcd_hal_cs_high();
}

//初始化lcd
//该初始化函数可以初始化各种ILI93XX液晶,但是其他函数是基于ILI9320的!!!
//在其他型号的驱动芯片上没有测试!
void lcd_hal_init(void)
{
	uu32 tick;
	
	// 关闭背光
	lcd_hal_rd_high();
	lcd_hal_wr_high();
	
	lcd_hal_io_init();
	
	// 等待电源稳定
	lcd_hal_rst_low();
	delay_ms(50);
	lcd_hal_rst_high();

	lcd_hal_cs_low();

	//HX8347A INIT
	lcd_hal_reg_sel(0x46);
	lcd_hal_dat_write(0x0095);
	lcd_hal_reg_sel(0x47);
	lcd_hal_dat_write(0x0051);
	lcd_hal_reg_sel(0x48);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x49);
	lcd_hal_dat_write(0x0036);
	lcd_hal_reg_sel(0x4a);
	lcd_hal_dat_write(0x0011);
	lcd_hal_reg_sel(0x4b);
	lcd_hal_dat_write(0x0066);
	lcd_hal_reg_sel(0x4c);
	lcd_hal_dat_write(0x0014);
	lcd_hal_reg_sel(0x4d);
	lcd_hal_dat_write(0x0077);
	lcd_hal_reg_sel(0x4e);
	lcd_hal_dat_write(0x0013);
	lcd_hal_reg_sel(0x4f);
	lcd_hal_dat_write(0x004c);
	lcd_hal_reg_sel(0x50);
	lcd_hal_dat_write(0x0046);
	lcd_hal_reg_sel(0x51);
	lcd_hal_dat_write(0x0046);

	//240x320 window setting
	lcd_hal_reg_sel(0x02);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x03);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x04);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x05);
	lcd_hal_dat_write(0x00ef);
	lcd_hal_reg_sel(0x06);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x07);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x08);
	lcd_hal_dat_write(0x0001);
	lcd_hal_reg_sel(0x09);
	lcd_hal_dat_write(0x003f);

	//Display Setting
	lcd_hal_reg_sel(0x01);
	lcd_hal_dat_write(0x0006);
	lcd_hal_reg_sel(0x16);
	lcd_hal_dat_write(0x00C8);	//内存模式 b8:(RGB/BRG) //地址增量方向
	lcd_hal_dat_write(0);
	lcd_hal_reg_sel(0x18);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x23);
	lcd_hal_dat_write(0x0095);
	lcd_hal_reg_sel(0x24);
	lcd_hal_dat_write(0x0095);
	lcd_hal_reg_sel(0x25);
	lcd_hal_dat_write(0x00ff);
	lcd_hal_reg_sel(0x27);
	lcd_hal_dat_write(0x0006);
	lcd_hal_reg_sel(0x28);
	lcd_hal_dat_write(0x0006);
	lcd_hal_reg_sel(0x29);
	lcd_hal_dat_write(0x0006);
	lcd_hal_reg_sel(0x2a);
	lcd_hal_dat_write(0x0006);
	//lcd_hal_reg_sel(0x2b);lcd_hal_dat_write(0x0006);
	lcd_hal_reg_sel(0x2c);
	lcd_hal_dat_write(0x0006);
	lcd_hal_reg_sel(0x2d);
	lcd_hal_dat_write(0x0006);

	lcd_hal_reg_sel(0x3a);
	lcd_hal_dat_write(0x0001);
	lcd_hal_reg_sel(0x3b);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x3c);
	lcd_hal_dat_write(0x00f0);
	lcd_hal_reg_sel(0x3d);
	lcd_hal_dat_write(0x0000);
	delay_ms(50);

	lcd_hal_reg_sel(0x35);
	lcd_hal_dat_write(0x0038);
	lcd_hal_reg_sel(0x36);
	lcd_hal_dat_write(0x0078);
	lcd_hal_reg_sel(0x3e);
	lcd_hal_dat_write(0x0038);
	lcd_hal_reg_sel(0x40);
	lcd_hal_dat_write(0x000f); //VCOMH  VCOM1~VCOM6
	lcd_hal_reg_sel(0x41);
	lcd_hal_dat_write(0x00f0);

	//Power Supply Setting
	lcd_hal_reg_sel(0x19);
	lcd_hal_dat_write(0x0049); // OSCADJ=010000);lcd_hal_dat_write( OSD_EN=1
	lcd_hal_reg_sel(0x93);
	lcd_hal_dat_write(0x000c);
	delay_ms(20);

	//for the setting before power supply startup
	lcd_hal_reg_sel(0x20);
	lcd_hal_dat_write(0x0040);
	lcd_hal_reg_sel(0x1d);
	lcd_hal_dat_write(0x0007);
	lcd_hal_reg_sel(0x1e);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x1f);
	lcd_hal_dat_write(0x0004);
	lcd_hal_reg_sel(0x44);
	lcd_hal_dat_write(0x004d); //VCOMH  VCOM1~VCOM6
	lcd_hal_reg_sel(0x45);
	lcd_hal_dat_write(0x0011); //VCOM   VD0~VD4
	delay_ms(10);

	//for power supply setting
	lcd_hal_reg_sel(0x1c);
	lcd_hal_dat_write(0x0004);
	delay_ms(10);
	lcd_hal_reg_sel(0x1b);
	lcd_hal_dat_write(0x0018);
	delay_ms(10);
	lcd_hal_reg_sel(0x1b);
	lcd_hal_dat_write(0x0010);
	delay_ms(10);
	lcd_hal_reg_sel(0x43);
	lcd_hal_dat_write(0x0080);
	delay_ms(10);

	lcd_hal_reg_sel(0x70);
	lcd_hal_dat_write(0x0006);
	lcd_hal_reg_sel(0x72);
	lcd_hal_dat_write(0x0001);
	//delay_ms(10);

	//Display ON Setting
	lcd_hal_reg_sel(0x90);
	lcd_hal_dat_write(0x007f);
	delay_ms(10);
	lcd_hal_reg_sel(0x26);
	lcd_hal_dat_write(0x0004);
	delay_ms(10);
	lcd_hal_reg_sel(0x26);
	lcd_hal_dat_write(0x0024);
	lcd_hal_reg_sel(0x26);
	lcd_hal_dat_write(0x002c);
	delay_ms(10);
	lcd_hal_reg_sel(0x26);
	lcd_hal_dat_write(0x003c);
	lcd_hal_reg_sel(0x21);
	lcd_hal_dat_write(0x0000);
	lcd_hal_reg_sel(0x22);

	lcd_hal_cs_high();

	// 关闭背光
	LCD_LED = 1; //点亮背光

	lcd_window_set(0,0, LCD_W-1, LCD_H-1);
	
	tick = app_tick_get();
	lcd_clear(COLOR_GEN(LIGHTBLUE));
	dbg_print("lcd fill time : %dms\n", app_tick_get() - tick);
}

//清屏函数
//Color:要清屏的填充色
void lcd_clear(u16 Color)
{
	u32 index = 0;
	
	lcd_window_set(0,0, LCD_W-1,LCD_H-1);

	lcd_write_gram_begin();		 //开始写入GRAM

	for (index = 0; index < LCD_W * LCD_H; index++)
	{
		lcd_write_gram(Color);
	}

	lcd_write_gram_end();
}
